home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / tms34010 / tms34010.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  57KB  |  1,860 lines

  1. /*** TMS34010: Portable Texas Instruments TMS34010 emulator *****************
  2.  
  3.     Copyright (C) Alex Pasadyn/Zsolt Vasvari 1998
  4.      Parts based on code by Aaron Giles
  5.  
  6. *****************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "driver.h"
  11. #include "osd_cpu.h"
  12. #include "cpuintrf.h"
  13. #include "mamedbg.h"
  14. #include "tms34010.h"
  15. #include "34010ops.h"
  16.  
  17. #ifdef MAME_DEBUG
  18. extern int debug_key_pressed;
  19. #endif
  20.  
  21. #define VERBOSE 0
  22.  
  23. #if VERBOSE
  24. #define LOG(x)    logerror x
  25. #else
  26. #define LOG(x)
  27. #endif
  28.  
  29.  
  30. static UINT8 tms34010_reg_layout[] = {
  31.     TMS34010_PC, TMS34010_SP, -1,
  32.     TMS34010_A0, TMS34010_B0, -1,
  33.     TMS34010_A1, TMS34010_B1, -1,
  34.     TMS34010_A2, TMS34010_B2, -1,
  35.     TMS34010_A3, TMS34010_B3, -1,
  36.     TMS34010_A4, TMS34010_B4, -1,
  37.     TMS34010_A5, TMS34010_B5, -1,
  38.     TMS34010_A6, TMS34010_B6, -1,
  39.     TMS34010_A7, TMS34010_B7, -1,
  40.     TMS34010_A8, TMS34010_B8, -1,
  41.     TMS34010_A9, TMS34010_B9, -1,
  42.     TMS34010_A10,TMS34010_B10,-1,
  43.     TMS34010_A11,TMS34010_B11,-1,
  44.     TMS34010_A12,TMS34010_B12,-1,
  45.     TMS34010_A13,TMS34010_B13,-1,
  46.     TMS34010_A14,TMS34010_B14, 0
  47. };
  48.  
  49. static UINT8 tms34010_win_layout[] = {
  50.     40, 0,39,17,    /* register window (top right) */
  51.      0, 0,39,17,    /* disassembler window (left, upper) */
  52.      0,18,39, 4,    /* memory #1 window (left, middle) */
  53.     40,18,39, 4,    /* memory #2 window (lower) */
  54.      0,23,80, 1     /* command line window (bottom rows) */
  55. };
  56.  
  57. /* TMS34010 State */
  58. typedef struct
  59. {
  60. #if LSB_FIRST
  61.     INT16 x;
  62.     INT16 y;
  63. #else
  64.     INT16 y;
  65.     INT16 x;
  66. #endif
  67. } XY;
  68.  
  69. typedef struct
  70. {
  71.     UINT32 op;
  72.     UINT32 pc;
  73.     UINT32 st;                    /* Only here so we can display it in the debug window */
  74.     union                        /* The register files are interleaved, so */
  75.     {                            /* that the SP occupies the same location in both */
  76.         INT32 Bregs[241];       /* Only every 16th entry is actually used */
  77.         XY BregsXY[241];
  78.         struct
  79.         {
  80.             INT32 unused[225];
  81.             union
  82.             {
  83.                 INT32 Aregs[16];
  84.                 XY AregsXY[16];
  85.             } a;
  86.         } a;
  87.     } regs;
  88.     UINT32 nflag;
  89.     UINT32 cflag;
  90.     UINT32 notzflag;  /* So we can just do an assignment to set it */
  91.     UINT32 vflag;
  92.     UINT32 pflag;
  93.     UINT32 ieflag;
  94.     UINT32 fe0flag;
  95.     UINT32 fe1flag;
  96.     UINT32 fw[2];
  97.     UINT32 fw_inc[2];  /* Same as fw[], except when fw = 0, fw_inc = 32 */
  98.     UINT16 IOregs[32];
  99.     UINT16 reset_deferred;
  100.     void (*F0_write) (UINT32 bitaddr, UINT32 data);
  101.     void (*F1_write) (UINT32 bitaddr, UINT32 data);
  102.      INT32 (*F0_read) (UINT32 bitaddr);
  103.      INT32 (*F1_read) (UINT32 bitaddr);
  104.     UINT32 (*pixel_write)(UINT32 address, UINT32 value);
  105.     UINT32 (*pixel_read)(UINT32 address);
  106.     UINT32 transparency;
  107.     UINT32 window_checking;
  108.      INT32 (*raster_op)(INT32 newpix, INT32 oldpix);
  109.     UINT32 lastpixaddr;
  110.     UINT32 lastpixword;
  111.     UINT32 lastpixwordchanged;
  112.     UINT32 xytolshiftcount1;
  113.     UINT32 xytolshiftcount2;
  114.     UINT16* shiftreg;
  115.     UINT8* stackbase;
  116.     UINT32 stackoffs;
  117.     int (*irq_callback)(int irqline);
  118.     int last_update_vcount;
  119.     struct tms34010_config *config;
  120. } TMS34010_Regs;
  121.  
  122. static TMS34010_Regs state;
  123. static TMS34010_Regs *host_interface_context;
  124. static UINT8 host_interface_cpu;
  125. static int *dpyint_timer[MAX_CPU];          /* Display interrupt timer */
  126. static int *vsblnk_timer[MAX_CPU];          /* VBLANK start timer */
  127. static UINT8* stackbase[MAX_CPU] = {0,0,0,0};
  128. static UINT32 stackoffs[MAX_CPU] = {0,0,0,0};
  129. static int first_reset = 1;                    /* cheesy, but gets the job done */
  130.  
  131. /* default configuration */
  132. static struct tms34010_config default_config =
  133. {
  134.     0,                    /* don't halt on reset */
  135.     NULL,                /* no interrupt callback */
  136.     NULL,                /* no shiftreg functions */
  137.     NULL                /* no shiftreg functions */
  138. };
  139.  
  140. static void check_interrupt(void);
  141.  
  142. static void (*wfield_functions[32]) (UINT32 bitaddr, UINT32 data) =
  143. {
  144.     wfield_32, wfield_01, wfield_02, wfield_03, wfield_04, wfield_05,
  145.     wfield_06, wfield_07, wfield_08, wfield_09, wfield_10, wfield_11,
  146.     wfield_12, wfield_13, wfield_14, wfield_15, wfield_16, wfield_17,
  147.     wfield_18, wfield_19, wfield_20, wfield_21, wfield_22, wfield_23,
  148.     wfield_24, wfield_25, wfield_26, wfield_27, wfield_28, wfield_29,
  149.     wfield_30, wfield_31
  150. };
  151. static INT32 (*rfield_functions_z[32]) (UINT32 bitaddr) =
  152. {
  153.     rfield_32  , rfield_z_01, rfield_z_02, rfield_z_03, rfield_z_04, rfield_z_05,
  154.     rfield_z_06, rfield_z_07, rfield_z_08, rfield_z_09, rfield_z_10, rfield_z_11,
  155.     rfield_z_12, rfield_z_13, rfield_z_14, rfield_z_15, rfield_z_16, rfield_z_17,
  156.     rfield_z_18, rfield_z_19, rfield_z_20, rfield_z_21, rfield_z_22, rfield_z_23,
  157.     rfield_z_24, rfield_z_25, rfield_z_26, rfield_z_27, rfield_z_28, rfield_z_29,
  158.     rfield_z_30, rfield_z_31
  159. };
  160. static INT32 (*rfield_functions_s[32]) (UINT32 bitaddr) =
  161. {
  162.     rfield_32  , rfield_s_01, rfield_s_02, rfield_s_03, rfield_s_04, rfield_s_05,
  163.     rfield_s_06, rfield_s_07, rfield_s_08, rfield_s_09, rfield_s_10, rfield_s_11,
  164.     rfield_s_12, rfield_s_13, rfield_s_14, rfield_s_15, rfield_s_16, rfield_s_17,
  165.     rfield_s_18, rfield_s_19, rfield_s_20, rfield_s_21, rfield_s_22, rfield_s_23,
  166.     rfield_s_24, rfield_s_25, rfield_s_26, rfield_s_27, rfield_s_28, rfield_s_29,
  167.     rfield_s_30, rfield_s_31
  168. };
  169.  
  170. /* public globals */
  171. int    tms34010_ICount;
  172.  
  173. /* context finder */
  174. #define FINDCONTEXT(_cpu) (cpu_is_saving_context(_cpu) ? cpu_getcontext(_cpu) : &state)
  175.  
  176. /* register definitions and shortcuts */
  177. #define PC         (state.pc)
  178. #define ST         (state.st)
  179. #define N_FLAG     (state.nflag)
  180. #define NOTZ_FLAG  (state.notzflag)
  181. #define C_FLAG     (state.cflag)
  182. #define V_FLAG     (state.vflag)
  183. #define P_FLAG     (state.pflag)
  184. #define IE_FLAG    (state.ieflag)
  185. #define FE0_FLAG   (state.fe0flag)
  186. #define FE1_FLAG   (state.fe1flag)
  187. #define AREG(i)    (state.regs.a.a.Aregs[i])
  188. #define AREG_XY(i) (state.regs.a.a.AregsXY[i])
  189. #define AREG_X(i)  (state.regs.a.a.AregsXY[i].x)
  190. #define AREG_Y(i)  (state.regs.a.a.AregsXY[i].y)
  191. #define BREG(i)    (state.regs.Bregs[i])
  192. #define BREG_XY(i) (state.regs.BregsXY[i])
  193. #define BREG_X(i)  (state.regs.BregsXY[i].x)
  194. #define BREG_Y(i)  (state.regs.BregsXY[i].y)
  195. #define SP         (state.regs.a.a.Aregs[15])
  196. #define FW(i)      (state.fw[i])
  197. #define FW_INC(i)  (state.fw_inc[i])
  198. #define ASRCREG  (((state.op)>>5)&0x0f)
  199. #define ADSTREG   ((state.op)    &0x0f)
  200. #define BSRCREG  (((state.op)&0x1e0)>>1)
  201. #define BDSTREG  (((state.op)&0x0f)<<4)
  202. #define SKIP_WORD (PC += (2<<3))
  203. #define SKIP_LONG (PC += (4<<3))
  204. #define PARAM_K   (((state.op)>>5)&0x1f)
  205. #define PARAM_N    ((state.op)&0x1f)
  206. #define PARAM_REL8 ((signed char) ((state.op)&0x00ff))
  207. #define WFIELD0(a,b) state.F0_write(a,b)
  208. #define WFIELD1(a,b) state.F1_write(a,b)
  209. #define RFIELD0(a)   state.F0_read(a)
  210. #define RFIELD1(a)   state.F1_read(a)
  211. #define WPIXEL(a,b)  state.pixel_write(a,b)
  212. #define RPIXEL(a)    state.pixel_read(a)
  213.  
  214. /* Implied Operands */
  215. #define SADDR        BREG(0<<4)
  216. #define SADDR_X   BREG_X(0<<4)
  217. #define SADDR_Y   BREG_Y(0<<4)
  218. #define SADDR_XY BREG_XY(0<<4)
  219. #define SPTCH       BREG(1<<4)
  220. #define DADDR       BREG(2<<4)
  221. #define DADDR_X   BREG_X(2<<4)
  222. #define DADDR_Y   BREG_Y(2<<4)
  223. #define DADDR_XY BREG_XY(2<<4)
  224. #define DPTCH       BREG(3<<4)
  225. #define OFFSET      BREG(4<<4)
  226. #define WSTART_X  BREG_X(5<<4)
  227. #define WSTART_Y  BREG_Y(5<<4)
  228. #define WEND_X    BREG_X(6<<4)
  229. #define WEND_Y    BREG_Y(6<<4)
  230. #define DYDX_X    BREG_X(7<<4)
  231. #define DYDX_Y    BREG_Y(7<<4)
  232. #define COLOR0      BREG(8<<4)
  233. #define COLOR1      BREG(9<<4)
  234. #define COUNT       BREG(10<<4)
  235. #define INC1_X    BREG_X(11<<4)
  236. #define INC1_Y    BREG_Y(11<<4)
  237. #define INC2_X    BREG_X(12<<4)
  238. #define INC2_Y    BREG_Y(12<<4)
  239. #define PATTRN      BREG(13<<4)
  240. #define TEMP        BREG(14<<4)
  241.  
  242. /* set the field widths - shortcut */
  243. INLINE void SET_FW(void)
  244. {
  245.     FW_INC(0) = (FW(0) ? FW(0) : 0x20);
  246.     FW_INC(1) = (FW(1) ? FW(1) : 0x20);
  247.  
  248.     state.F0_write = wfield_functions[FW(0)];
  249.     state.F1_write = wfield_functions[FW(1)];
  250.  
  251.     if (FE0_FLAG)
  252.     {
  253.         state.F0_read  = rfield_functions_s[FW(0)];    /* Sign extend */
  254.     }
  255.     else
  256.     {
  257.         state.F0_read  = rfield_functions_z[FW(0)];    /* Zero extend */
  258.     }
  259.  
  260.     if (FE1_FLAG)
  261.     {
  262.         state.F1_read  = rfield_functions_s[FW(1)];    /* Sign extend */
  263.     }
  264.     else
  265.     {
  266.         state.F1_read  = rfield_functions_z[FW(1)];    /* Zero extend */
  267.     }
  268. }
  269.  
  270. /* Intialize Status to 0x0010 */
  271. INLINE void RESET_ST(void)
  272. {
  273.     N_FLAG = C_FLAG = V_FLAG = P_FLAG = IE_FLAG = FE0_FLAG = FE1_FLAG = 0;
  274.     NOTZ_FLAG = 1;
  275.     FW(0) = 0x10;
  276.     FW(1) = 0;
  277.     SET_FW();
  278. }
  279.  
  280. /* Combine indiviual flags into the Status Register */
  281. INLINE UINT32 GET_ST(void)
  282. {
  283.     return (     N_FLAG ? 0x80000000 : 0) |
  284.            (     C_FLAG ? 0x40000000 : 0) |
  285.            (  NOTZ_FLAG ? 0 : 0x20000000) |
  286.            (     V_FLAG ? 0x10000000 : 0) |
  287.            (     P_FLAG ? 0x02000000 : 0) |
  288.            (    IE_FLAG ? 0x00200000 : 0) |
  289.            (   FE0_FLAG ? 0x00000020 : 0) |
  290.            (   FE1_FLAG ? 0x00000800 : 0) |
  291.            FW(0) |
  292.           (FW(1) << 6);
  293. }
  294.  
  295. /* Break up Status Register into indiviual flags */
  296. INLINE void SET_ST(UINT32 st)
  297. {
  298.     N_FLAG    =    st & 0x80000000;
  299.     C_FLAG    =    st & 0x40000000;
  300.     NOTZ_FLAG =  !(st & 0x20000000);
  301.     V_FLAG    =    st & 0x10000000;
  302.     P_FLAG    =    st & 0x02000000;
  303.     IE_FLAG   =    st & 0x00200000;
  304.     FE0_FLAG  =    st & 0x00000020;
  305.     FE1_FLAG  =    st & 0x00000800;
  306.     FW(0)     =    st & 0x1f;
  307.     FW(1)     =   (st >> 6) & 0x1f;
  308.     SET_FW();
  309.  
  310.     /* interrupts might have been enabled, check it */
  311.     check_interrupt();
  312. }
  313.  
  314. /* shortcuts for reading opcodes */
  315. INLINE UINT32 ROPCODE (void)
  316. {
  317.     UINT32 pc = TOBYTE(PC);
  318.     PC += (2<<3);
  319.     return cpu_readop16(pc);
  320. }
  321. INLINE INT16 PARAM_WORD (void)
  322. {
  323.     UINT32 pc = TOBYTE(PC);
  324.     PC += (2<<3);
  325.     return cpu_readop_arg16(pc);
  326. }
  327. INLINE INT16 PARAM_WORD_NO_INC (void)
  328. {
  329.     return cpu_readop_arg16(TOBYTE(PC));
  330. }
  331. INLINE INT32 PARAM_LONG_NO_INC (void)
  332. {
  333.     UINT32 pc = TOBYTE(PC);
  334.     return cpu_readop_arg16(pc) | ((UINT32)(UINT16)cpu_readop_arg16(pc+2) << 16);
  335. }
  336. INLINE INT32 PARAM_LONG (void)
  337. {
  338.     INT32 ret = PARAM_LONG_NO_INC();
  339.     PC += (4<<3);
  340.     return ret;
  341. }
  342.  
  343. /* read memory byte */
  344. INLINE INT8 RBYTE (UINT32 bitaddr)
  345. {
  346.     RFIELDMAC_Z_8;
  347. }
  348.  
  349. /* write memory byte */
  350. INLINE void WBYTE (UINT32 bitaddr, UINT32 data)
  351. {
  352.     WFIELDMAC_8;
  353. }
  354.  
  355. /* read memory long */
  356. INLINE INT32 RLONG (UINT32 bitaddr)
  357. {
  358.     RFIELDMAC_32;
  359. }
  360. /* write memory long */
  361. INLINE void WLONG (UINT32 bitaddr, UINT32 data)
  362. {
  363.     WFIELDMAC_32;
  364. }
  365.  
  366.  
  367. /* pushes/pops a value from the stack
  368.  
  369.    These are called millions of times. If you change it, please test effect
  370.    on performance */
  371.  
  372. INLINE void PUSH (UINT32 data)
  373. {
  374. #if TMS34010_FAST_STACK
  375.     UINT8* base;
  376.     SP -= 0x20;
  377.     base = STACKPTR(SP);
  378.     WRITE_WORD(base, (UINT16)data);
  379.     WRITE_WORD(base+2, data >> 16);
  380. #else
  381.     SP -= 0x20;
  382.     TMS34010_WRMEM_DWORD(TOBYTE(SP), data);
  383. #endif
  384. }
  385.  
  386. INLINE INT32 POP (void)
  387. {
  388. #if TMS34010_FAST_STACK
  389.     UINT8* base = STACKPTR(SP);
  390.     INT32 ret = READ_WORD(base) + (READ_WORD(base+2) << 16);
  391.     SP += 0x20;
  392.     return ret;
  393. #else
  394.     INT32 ret = TMS34010_RDMEM_DWORD(TOBYTE(SP));
  395.     SP += 0x20;
  396.     return ret;
  397. #endif
  398. }
  399.  
  400.  
  401. /* No Raster Op + No Transparency */
  402. #define WP(m1,m2)                                                                          \
  403.     UINT32 boundary = 0;                                                                 \
  404.     UINT32 a = TOBYTE(address&0xfffffff0);                                                \
  405.     UINT32 shiftcount = (address&m1);                                                    \
  406.     if (state.lastpixaddr != a)                                                            \
  407.     {                                                                                    \
  408.         if (state.lastpixaddr != INVALID_PIX_ADDRESS)                                    \
  409.         {                                                                                \
  410.             TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword);                    \
  411.             boundary = 1;                                                                \
  412.         }                                                                                \
  413.         state.lastpixword = TMS34010_RDMEM_WORD(a);                                        \
  414.         state.lastpixaddr = a;                                                            \
  415.     }                                                                                    \
  416.                                                                                         \
  417.     /* TODO: plane masking */                                                            \
  418.                                                                                         \
  419.     value &= m2;                                                                        \
  420.     state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount);    \
  421.                                                                                         \
  422.     return boundary;
  423.  
  424.  
  425. /* No Raster Op + Transparency */
  426. #define WP_T(m1,m2)                                                                      \
  427.     UINT32 boundary = 0;                                                                 \
  428.     UINT32 a = TOBYTE(address&0xfffffff0);                                                \
  429.     if (state.lastpixaddr != a)                                                            \
  430.     {                                                                                    \
  431.         if (state.lastpixaddr != INVALID_PIX_ADDRESS)                                    \
  432.         {                                                                                \
  433.             if (state.lastpixwordchanged)                                                \
  434.             {                                                                            \
  435.                 TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword);                \
  436.             }                                                                            \
  437.             boundary = 1;                                                                \
  438.         }                                                                                \
  439.         state.lastpixword = TMS34010_RDMEM_WORD(a);                                        \
  440.         state.lastpixaddr = a;                                                            \
  441.         state.lastpixwordchanged = 0;                                                    \
  442.     }                                                                                    \
  443.                                                                                         \
  444.     /* TODO: plane masking */                                                            \
  445.                                                                                         \
  446.     value &= m2;                                                                        \
  447.     if (value)                                                                            \
  448.     {                                                                                    \
  449.         UINT32 shiftcount = (address&m1);                                                \
  450.         state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount);    \
  451.         state.lastpixwordchanged = 1;                                                    \
  452.     }                                                                                      \
  453.                                                                                         \
  454.     return boundary;
  455.  
  456.  
  457. /* Raster Op + No Transparency */
  458. #define WP_R(m1,m2)                                                                      \
  459.     UINT32 oldpix;                                                                        \
  460.     UINT32 boundary = 0;                                                                 \
  461.     UINT32 a = TOBYTE(address&0xfffffff0);                                                \
  462.     UINT32 shiftcount = (address&m1);                                                    \
  463.     if (state.lastpixaddr != a)                                                            \
  464.     {                                                                                    \
  465.         if (state.lastpixaddr != INVALID_PIX_ADDRESS)                                    \
  466.         {                                                                                \
  467.             TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword);                    \
  468.             boundary = 1;                                                                \
  469.         }                                                                                \
  470.         state.lastpixword = TMS34010_RDMEM_WORD(a);                                        \
  471.         state.lastpixaddr = a;                                                            \
  472.     }                                                                                    \
  473.                                                                                         \
  474.     /* TODO: plane masking */                                                            \
  475.                                                                                         \
  476.     oldpix = (state.lastpixword >> shiftcount) & m2;                                    \
  477.     value = state.raster_op(value & m2, oldpix) & m2;                                    \
  478.                                                                                         \
  479.     state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount);    \
  480.                                                                                         \
  481.     return boundary;
  482.  
  483.  
  484. /* Raster Op + Transparency */
  485. #define WP_R_T(m1,m2)                                                                      \
  486.     UINT32 oldpix;                                                                        \
  487.     UINT32 boundary = 0;                                                                 \
  488.     UINT32 a = TOBYTE(address&0xfffffff0);                                                \
  489.     UINT32 shiftcount = (address&m1);                                                    \
  490.     if (state.lastpixaddr != a)                                                            \
  491.     {                                                                                    \
  492.         if (state.lastpixaddr != INVALID_PIX_ADDRESS)                                    \
  493.         {                                                                                \
  494.             if (state.lastpixwordchanged)                                                \
  495.             {                                                                            \
  496.                 TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword);                \
  497.             }                                                                            \
  498.             boundary = 1;                                                                \
  499.         }                                                                                \
  500.         state.lastpixword = TMS34010_RDMEM_WORD(a);                                        \
  501.         state.lastpixaddr = a;                                                            \
  502.         state.lastpixwordchanged = 0;                                                    \
  503.     }                                                                                    \
  504.                                                                                         \
  505.     /* TODO: plane masking */                                                            \
  506.                                                                                         \
  507.     oldpix = (state.lastpixword >> shiftcount) & m2;                                    \
  508.     value = state.raster_op(value & m2, oldpix) & m2;                                    \
  509.                                                                                         \
  510.     if (value)                                                                            \
  511.     {                                                                                    \
  512.         state.lastpixword = (state.lastpixword & ~(m2<<shiftcount)) | (value<<shiftcount);    \
  513.         state.lastpixwordchanged = 1;                                                    \
  514.     }                                                                                      \
  515.                                                                                         \
  516.     return boundary;
  517.  
  518.  
  519. /* These functions return 'true' on word boundary, 'false' otherwise */
  520.  
  521. /* No Raster Op + No Transparency */
  522. static UINT32 write_pixel_1 (UINT32 address, UINT32 value) { WP(0x0f,0x01); }
  523. static UINT32 write_pixel_2 (UINT32 address, UINT32 value) { WP(0x0e,0x03); }
  524. static UINT32 write_pixel_4 (UINT32 address, UINT32 value) { WP(0x0c,0x0f); }
  525. static UINT32 write_pixel_8 (UINT32 address, UINT32 value) { WP(0x08,0xff); }
  526. static UINT32 write_pixel_16(UINT32 address, UINT32 value)
  527. {
  528.     /* TODO: plane masking */
  529.  
  530.     TMS34010_WRMEM_WORD(TOBYTE(address&0xfffffff0), value);
  531.     return 1;
  532. }
  533.  
  534.  
  535. /* No Raster Op + Transparency */
  536. static UINT32 write_pixel_t_1 (UINT32 address, UINT32 value) { WP_T(0x0f,0x01); }
  537. static UINT32 write_pixel_t_2 (UINT32 address, UINT32 value) { WP_T(0x0e,0x03); }
  538. static UINT32 write_pixel_t_4 (UINT32 address, UINT32 value) { WP_T(0x0c,0x0f); }
  539. static UINT32 write_pixel_t_8 (UINT32 address, UINT32 value) { WP_T(0x08,0xff); }
  540. static UINT32 write_pixel_t_16(UINT32 address, UINT32 value)
  541. {
  542.     /* TODO: plane masking */
  543.  
  544.     /* Transparency checking */
  545.     if (value)
  546.     {
  547.         TMS34010_WRMEM_WORD(TOBYTE(address&0xfffffff0), value);
  548.     }
  549.  
  550.     return 1;
  551. }
  552.  
  553.  
  554. /* Raster Op + No Transparency */
  555. static UINT32 write_pixel_r_1 (UINT32 address, UINT32 value) { WP_R(0x0f,0x01); }
  556. static UINT32 write_pixel_r_2 (UINT32 address, UINT32 value) { WP_R(0x0e,0x03); }
  557. static UINT32 write_pixel_r_4 (UINT32 address, UINT32 value) { WP_R(0x0c,0x0f); }
  558. static UINT32 write_pixel_r_8 (UINT32 address, UINT32 value) { WP_R(0x08,0xff); }
  559. static UINT32 write_pixel_r_16(UINT32 address, UINT32 value)
  560. {
  561.     /* TODO: plane masking */
  562.  
  563.     UINT32 a = TOBYTE(address&0xfffffff0);
  564.  
  565.     TMS34010_WRMEM_WORD(a, state.raster_op(value, TMS34010_RDMEM_WORD(a)));
  566.  
  567.     return 1;
  568. }
  569.  
  570.  
  571. /* Raster Op + Transparency */
  572. static UINT32 write_pixel_r_t_1 (UINT32 address, UINT32 value) { WP_R_T(0x0f,0x01); }
  573. static UINT32 write_pixel_r_t_2 (UINT32 address, UINT32 value) { WP_R_T(0x0e,0x03); }
  574. static UINT32 write_pixel_r_t_4 (UINT32 address, UINT32 value) { WP_R_T(0x0c,0x0f); }
  575. static UINT32 write_pixel_r_t_8 (UINT32 address, UINT32 value) { WP_R_T(0x08,0xff); }
  576. static UINT32 write_pixel_r_t_16(UINT32 address, UINT32 value)
  577. {
  578.     /* TODO: plane masking */
  579.  
  580.     UINT32 a = TOBYTE(address&0xfffffff0);
  581.     value = state.raster_op(value, TMS34010_RDMEM_WORD(a));
  582.  
  583.     /* Transparency checking */
  584.     if (value)
  585.     {
  586.         TMS34010_WRMEM_WORD(a, value);
  587.     }
  588.  
  589.     return 1;
  590. }
  591.  
  592.  
  593.  
  594. #define RP(m1,m2)                                              \
  595.     /* TODO: Plane masking */                                \
  596.     return (TMS34010_RDMEM_WORD(TOBYTE(address&0xfffffff0)) >> (address&m1)) & m2;
  597.  
  598. static UINT32 read_pixel_1 (UINT32 address) { RP(0x0f,0x01) }
  599. static UINT32 read_pixel_2 (UINT32 address) { RP(0x0e,0x03) }
  600. static UINT32 read_pixel_4 (UINT32 address) { RP(0x0c,0x0f) }
  601. static UINT32 read_pixel_8 (UINT32 address) { RP(0x08,0xff) }
  602. static UINT32 read_pixel_16(UINT32 address)
  603. {
  604.     /* TODO: Plane masking */
  605.     return TMS34010_RDMEM_WORD(TOBYTE(address&0xfffffff0));
  606. }
  607.  
  608.  
  609. #define FINISH_PIX_OP                                                \
  610.     if (state.lastpixaddr != INVALID_PIX_ADDRESS)                    \
  611.     {                                                                \
  612.         TMS34010_WRMEM_WORD(state.lastpixaddr, state.lastpixword);    \
  613.     }                                                                \
  614.     state.lastpixaddr = INVALID_PIX_ADDRESS;                        \
  615.     P_FLAG = 0;
  616.  
  617.  
  618. static UINT32 write_pixel_shiftreg (UINT32 address, UINT32 value)
  619. {
  620.     if (state.config->from_shiftreg)
  621.         state.config->from_shiftreg(address, &state.shiftreg[0]);
  622.     else
  623.         logerror("From ShiftReg function not set. PC = %08X\n", PC);
  624.     return 1;
  625. }
  626.  
  627. static UINT32 read_pixel_shiftreg (UINT32 address)
  628. {
  629.     if (state.config->to_shiftreg)
  630.         state.config->to_shiftreg(address, &state.shiftreg[0]);
  631.     else
  632.         logerror("To ShiftReg function not set. PC = %08X\n", PC);
  633.     return state.shiftreg[0];
  634. }
  635.  
  636. /* includes the static function prototypes and the master opcode table */
  637. #include "34010tbl.c"
  638.  
  639. /* includes the actual opcode implementations */
  640. #include "34010ops.c"
  641. #include "34010gfx.c"
  642.  
  643.  
  644. /* Raster operations */
  645. static INT32 raster_op_1(INT32 newpix, INT32 oldpix)
  646. {
  647.     /*  S AND D -> D */
  648.     return newpix & oldpix;
  649. }
  650. static INT32 raster_op_2(INT32 newpix, INT32 oldpix)
  651. {
  652.     /*  S AND ~D -> D */
  653.     return newpix & ~oldpix;
  654. }
  655. static INT32 raster_op_3(INT32 newpix, INT32 oldpix)
  656. {
  657.     /*  0 -> D */
  658.     return 0;
  659. }
  660. static INT32 raster_op_4(INT32 newpix, INT32 oldpix)
  661. {
  662.     /*  S OR ~D -> D */
  663.     return newpix | ~oldpix;
  664. }
  665. static INT32 raster_op_5(INT32 newpix, INT32 oldpix)
  666. {
  667.     /* FIXME!!! Not sure about this one? */
  668.     /*  S XNOR D -> D */
  669.     return ~(newpix ^ oldpix);
  670. }
  671. static INT32 raster_op_6(INT32 newpix, INT32 oldpix)
  672. {
  673.     /*  ~D -> D */
  674.     return ~oldpix;
  675. }
  676. static INT32 raster_op_7(INT32 newpix, INT32 oldpix)
  677. {
  678.     /*  S NOR D -> D */
  679.     return ~(newpix | oldpix);
  680. }
  681. static INT32 raster_op_8(INT32 newpix, INT32 oldpix)
  682. {
  683.     /*  S OR D -> D */
  684.     return newpix | oldpix;
  685. }
  686. static INT32 raster_op_9(INT32 newpix, INT32 oldpix)
  687. {
  688.     /*  D -> D */
  689.     return oldpix;
  690. }
  691. static INT32 raster_op_10(INT32 newpix, INT32 oldpix)
  692. {
  693.     /*  S XOR D -> D */
  694.     return newpix ^ oldpix;
  695. }
  696. static INT32 raster_op_11(INT32 newpix, INT32 oldpix)
  697. {
  698.     /*  ~S AND D -> D */
  699.     return ~newpix & oldpix;
  700. }
  701. static INT32 raster_op_12(INT32 newpix, INT32 oldpix)
  702. {
  703.     /*  1 -> D */
  704.     return 0xffff;
  705. }
  706. static INT32 raster_op_13(INT32 newpix, INT32 oldpix)
  707. {
  708.     /*  ~S OR D -> D */
  709.     return ~newpix | oldpix;
  710. }
  711. static INT32 raster_op_14(INT32 newpix, INT32 oldpix)
  712. {
  713.     /*  S NAND D -> D */
  714.     return ~(newpix & oldpix);
  715. }
  716. static INT32 raster_op_15(INT32 newpix, INT32 oldpix)
  717. {
  718.     /*  ~S -> D */
  719.     return ~newpix;
  720. }
  721. static INT32 raster_op_16(INT32 newpix, INT32 oldpix)
  722. {
  723.     /*  S + D -> D */
  724.     return newpix + oldpix;
  725. }
  726. static INT32 raster_op_17(INT32 newpix, INT32 oldpix)
  727. {
  728.     /*  S + D -> D with Saturation*/
  729.     INT32 max = (UINT32)0xffffffff>>(32-IOREG(REG_PSIZE));
  730.     INT32 res = newpix + oldpix;
  731.     return (res > max) ? max : res;
  732. }
  733. static INT32 raster_op_18(INT32 newpix, INT32 oldpix)
  734. {
  735.     /*  D - S -> D */
  736.     return oldpix - newpix;
  737. }
  738. static INT32 raster_op_19(INT32 newpix, INT32 oldpix)
  739. {
  740.     /*  D - S -> D with Saturation */
  741.     INT32 res = oldpix - newpix;
  742.     return (res < 0) ? 0 : res;
  743. }
  744. static INT32 raster_op_20(INT32 newpix, INT32 oldpix)
  745. {
  746.     /*  MAX(S,D) -> D */
  747.     return ((oldpix > newpix) ? oldpix : newpix);
  748. }
  749. static INT32 raster_op_21(INT32 newpix, INT32 oldpix)
  750. {
  751.     /*  MIN(S,D) -> D */
  752.     return ((oldpix > newpix) ? newpix : oldpix);
  753. }
  754.  
  755.  
  756. /****************************************************************************
  757.  * Reset the CPU emulation
  758.  ****************************************************************************/
  759. void tms34010_reset(void *param)
  760. {
  761.     struct tms34010_config *config = param ? param : &default_config;
  762.     int cpunum = cpu_getactivecpu();
  763.     int i;
  764.  
  765.     /* zap the state and copy in the config pointer */
  766.     memset(&state, 0, sizeof(state));
  767.     state.lastpixaddr = INVALID_PIX_ADDRESS;
  768.     state.config = config;
  769.  
  770.     /* allocate the shiftreg */
  771.     state.shiftreg = malloc(SHIFTREG_SIZE);
  772.  
  773.     /* fetch the initial PC and reset the state */
  774.     PC = RLONG(0xffffffe0);
  775.     change_pc29(PC)
  776.     RESET_ST();
  777.  
  778.     /* set up the speedy stack (this gets us into trouble later, though!) */
  779.     if (stackbase[cpunum] == 0)
  780.         logerror("Stack Base not set on CPU #%d\n", cpunum);
  781.     state.stackbase = stackbase[cpunum] - stackoffs[cpunum];
  782.  
  783.     /* HALT the CPU if requested, and remember to re-read the starting PC */
  784.     /* the first time we are run */
  785.     state.reset_deferred = config->halt_on_reset;
  786.     if (config->halt_on_reset)
  787.         TMS34010_io_register_w(REG_HSTCTLH * 2, 0x8000);
  788.  
  789.     /* reset the timers and the host interface (but only the first time) */
  790.     host_interface_context = NULL;
  791.     if (first_reset)
  792.     {
  793.         for (i = 0; i < MAX_CPU; i++)
  794.             dpyint_timer[i] = vsblnk_timer[i] = NULL;
  795.         first_reset = 0;
  796.     }
  797. }
  798.  
  799. /****************************************************************************
  800.  * Shut down the CPU emulation
  801.  ****************************************************************************/
  802. void tms34010_exit(void)
  803. {
  804.     first_reset = 1;
  805. }
  806.  
  807. /****************************************************************************
  808.  * Get all registers in given buffer
  809.  ****************************************************************************/
  810. unsigned tms34010_get_context(void *dst)
  811. {
  812.     if( dst )
  813.         *(TMS34010_Regs*)dst = state;
  814.     return sizeof(TMS34010_Regs);
  815. }
  816.  
  817. /****************************************************************************
  818.  * Set all registers to given values
  819.  ****************************************************************************/
  820. void tms34010_set_context(void *src)
  821. {
  822.     if( src )
  823.         state = *(TMS34010_Regs*)src;
  824.     change_pc29(PC)
  825.     check_interrupt();
  826. }
  827.  
  828. /****************************************************************************
  829.  * Return program counter
  830.  ****************************************************************************/
  831. unsigned tms34010_get_pc(void)
  832. {
  833.     return PC;
  834. }
  835.  
  836.  
  837. /****************************************************************************
  838.  * Set program counter
  839.  ****************************************************************************/
  840. void tms34010_set_pc(unsigned val)
  841. {
  842.     PC = val;
  843.     change_pc29(PC)
  844. }
  845.  
  846.  
  847. /****************************************************************************
  848.  * Return stack pointer
  849.  ****************************************************************************/
  850. unsigned tms34010_get_sp(void)
  851. {
  852.     return SP;
  853. }
  854.  
  855.  
  856. /****************************************************************************
  857.  * Set stack pointer
  858.  ****************************************************************************/
  859. void tms34010_set_sp(unsigned val)
  860. {
  861.     SP = val;
  862. }
  863.  
  864.  
  865. /****************************************************************************
  866.  * Return a specific register
  867.  ****************************************************************************/
  868. unsigned tms34010_get_reg(int regnum)
  869. {
  870.     switch( regnum )
  871.     {
  872.         case TMS34010_PC:  return PC;
  873.         case TMS34010_SP:  return SP;
  874.         case TMS34010_ST:  return ST;
  875.         case TMS34010_A0:  return AREG( 0);
  876.         case TMS34010_A1:  return AREG( 1);
  877.         case TMS34010_A2:  return AREG( 2);
  878.         case TMS34010_A3:  return AREG( 3);
  879.         case TMS34010_A4:  return AREG( 4);
  880.         case TMS34010_A5:  return AREG( 5);
  881.         case TMS34010_A6:  return AREG( 6);
  882.         case TMS34010_A7:  return AREG( 7);
  883.         case TMS34010_A8:  return AREG( 8);
  884.         case TMS34010_A9:  return AREG( 9);
  885.         case TMS34010_A10: return AREG(10);
  886.         case TMS34010_A11: return AREG(11);
  887.         case TMS34010_A12: return AREG(12);
  888.         case TMS34010_A13: return AREG(13);
  889.         case TMS34010_A14: return AREG(14);
  890.         case TMS34010_B0:  return BREG( 0<<4);
  891.         case TMS34010_B1:  return BREG( 1<<4);
  892.         case TMS34010_B2:  return BREG( 2<<4);
  893.         case TMS34010_B3:  return BREG( 3<<4);
  894.         case TMS34010_B4:  return BREG( 4<<4);
  895.         case TMS34010_B5:  return BREG( 5<<4);
  896.         case TMS34010_B6:  return BREG( 6<<4);
  897.         case TMS34010_B7:  return BREG( 7<<4);
  898.         case TMS34010_B8:  return BREG( 8<<4);
  899.         case TMS34010_B9:  return BREG( 9<<4);
  900.         case TMS34010_B10: return BREG(10<<4);
  901.         case TMS34010_B11: return BREG(11<<4);
  902.         case TMS34010_B12: return BREG(12<<4);
  903.         case TMS34010_B13: return BREG(13<<4);
  904.         case TMS34010_B14: return BREG(14<<4);
  905. /* TODO: return contents of [SP + wordsize * (CPU_SP_CONTENTS-regnum)] */
  906.         default:
  907.             if( regnum <= REG_SP_CONTENTS )
  908.             {
  909.                 unsigned offset = SP + 4 * (REG_SP_CONTENTS - regnum);
  910.                 return cpu_readmem29_dword( offset >> 3 );
  911.             }
  912.     }
  913.     return 0;
  914. }
  915.  
  916.  
  917. /****************************************************************************
  918.  * Set a specific register
  919.  ****************************************************************************/
  920. void tms34010_set_reg(int regnum, unsigned val)
  921. {
  922.     switch( regnum )
  923.     {
  924.         case TMS34010_PC:  PC = val; break;
  925.         case TMS34010_SP:  SP = val; break;
  926.         case TMS34010_ST:  ST = val; break;
  927.         case TMS34010_A0:  AREG( 0) = val; break;
  928.         case TMS34010_A1:  AREG( 1) = val; break;
  929.         case TMS34010_A2:  AREG( 2) = val; break;
  930.         case TMS34010_A3:  AREG( 3) = val; break;
  931.         case TMS34010_A4:  AREG( 4) = val; break;
  932.         case TMS34010_A5:  AREG( 5) = val; break;
  933.         case TMS34010_A6:  AREG( 6) = val; break;
  934.         case TMS34010_A7:  AREG( 7) = val; break;
  935.         case TMS34010_A8:  AREG( 8) = val; break;
  936.         case TMS34010_A9:  AREG( 9) = val; break;
  937.         case TMS34010_A10: AREG(10) = val; break;
  938.         case TMS34010_A11: AREG(11) = val; break;
  939.         case TMS34010_A12: AREG(12) = val; break;
  940.         case TMS34010_A13: AREG(13) = val; break;
  941.         case TMS34010_A14: AREG(14) = val; break;
  942.         case TMS34010_B0:  BREG( 0<<4) = val; break;
  943.         case TMS34010_B1:  BREG( 1<<4) = val; break;
  944.         case TMS34010_B2:  BREG( 2<<4) = val; break;
  945.         case TMS34010_B3:  BREG( 3<<4) = val; break;
  946.         case TMS34010_B4:  BREG( 4<<4) = val; break;
  947.         case TMS34010_B5:  BREG( 5<<4) = val; break;
  948.         case TMS34010_B6:  BREG( 6<<4) = val; break;
  949.         case TMS34010_B7:  BREG( 7<<4) = val; break;
  950.         case TMS34010_B8:  BREG( 8<<4) = val; break;
  951.         case TMS34010_B9:  BREG( 9<<4) = val; break;
  952.         case TMS34010_B10: BREG(10<<4) = val; break;
  953.         case TMS34010_B11: BREG(11<<4) = val; break;
  954.         case TMS34010_B12: BREG(12<<4) = val; break;
  955.         case TMS34010_B13: BREG(13<<4) = val; break;
  956.         case TMS34010_B14: BREG(14<<4) = val; break;
  957. /* TODO: set contents of [SP + wordsize * (CPU_SP_CONTENTS-regnum)] */
  958.         default:
  959.             if( regnum <= REG_SP_CONTENTS )
  960.             {
  961.                 unsigned offset = SP + 4 * (REG_SP_CONTENTS - regnum);
  962.                 cpu_writemem29_word( offset >> 3, val ); /* ??? */
  963.             }
  964.     }
  965. }
  966.  
  967.  
  968. TMS34010_Regs* TMS34010_GetState(void)
  969. {
  970.     return &state;
  971. }
  972.  
  973.  
  974. /****************************************************************************
  975.  * Set NMI line state
  976.  ****************************************************************************/
  977. void tms34010_set_nmi_line(int linestate)
  978. {
  979.     /* Does not apply: the NMI is an internal interrupt for the TMS34010 */
  980. }
  981.  
  982. /****************************************************************************
  983.  * Set IRQ line state
  984.  ****************************************************************************/
  985. void tms34010_set_irq_line(int irqline, int linestate)
  986. {
  987.     LOG(("TMS34010#%d set irq line %d state %d\n", cpu_getactivecpu(), irqline, linestate));
  988.     if (linestate != CLEAR_LINE)
  989.     {
  990.         /* set the pending interrupt */
  991.         switch (irqline)
  992.         {
  993.         case 0:
  994.             IOREG(REG_INTPEND) |= TMS34010_INT1;
  995.             break;
  996.         case 1:
  997.             IOREG(REG_INTPEND) |= TMS34010_INT2;
  998.             break;
  999.         }
  1000.  
  1001.         check_interrupt();
  1002.     }
  1003. }
  1004.  
  1005. void tms34010_set_irq_callback(int (*callback)(int irqline))
  1006. {
  1007.     state.irq_callback = callback;
  1008. }
  1009.  
  1010. void tms34010_internal_interrupt(int type)
  1011. {
  1012.     LOG(("TMS34010#%d set internal interrupt $%04x\n", cpu_getactivecpu(), type));
  1013.     IOREG(REG_INTPEND) |= type;
  1014.     check_interrupt();
  1015. }
  1016.  
  1017. /* Generate pending interrupts. Do NOT inline this function on DJGPP,
  1018.    it causes a slowdown */
  1019. static void check_interrupt(void)
  1020. {
  1021.     int vector=0;
  1022.     int irqline = -1;
  1023.  
  1024.     if (!IOREG(REG_INTPEND))
  1025.     {
  1026.         /* No interrupts pending, get out quickly */
  1027.         return;
  1028.     }
  1029.  
  1030.     if (IOREG(REG_INTPEND) & TMS34010_NMI)
  1031.     {
  1032.         LOG(("TMS34010#%d takes NMI\n", cpu_getactivecpu()));
  1033.         IOREG(REG_INTPEND) &= ~TMS34010_NMI;
  1034.  
  1035.         if (!(IOREG(REG_HSTCTLH) & 0x0200))  /* NMI mode bit */
  1036.         {
  1037.             PUSH(PC);
  1038.             PUSH(GET_ST());
  1039.         }
  1040.         RESET_ST();
  1041.         PC = RLONG(0xfffffee0);
  1042.         change_pc29(PC);
  1043.     }
  1044.     else
  1045.     {
  1046.         if (!IE_FLAG)
  1047.         {
  1048.             /* Global interrupt disable */
  1049.             return;
  1050.         }
  1051.  
  1052.         if ((IOREG(REG_INTPEND) & TMS34010_HI) &&
  1053.             (IOREG(REG_INTENB)  & TMS34010_HI))
  1054.         {
  1055.             LOG(("TMS34010#%d takes HI\n", cpu_getactivecpu()));
  1056.             vector = 0xfffffec0;
  1057.         }
  1058.         else
  1059.         if ((IOREG(REG_INTPEND) & TMS34010_DI) &&
  1060.             (IOREG(REG_INTENB)  & TMS34010_DI))
  1061.         {
  1062.             LOG(("TMS34010#%d takes DI\n", cpu_getactivecpu()));
  1063.             vector = 0xfffffea0;
  1064.         }
  1065.         else
  1066.         if ((IOREG(REG_INTPEND) & TMS34010_WV) &&
  1067.             (IOREG(REG_INTENB)  & TMS34010_WV))
  1068.         {
  1069.             LOG(("TMS34010#%d takes WV\n", cpu_getactivecpu()));
  1070.             vector = 0xfffffe80;
  1071.         }
  1072.         else
  1073.         if ((IOREG(REG_INTPEND) & TMS34010_INT1) &&
  1074.             (IOREG(REG_INTENB)    & TMS34010_INT1))
  1075.         {
  1076.             LOG(("TMS34010#%d takes INT1\n", cpu_getactivecpu()));
  1077.             vector = 0xffffffc0;
  1078.             irqline = 0;
  1079.         }
  1080.         else
  1081.         if ((IOREG(REG_INTPEND) & TMS34010_INT2) &&
  1082.             (IOREG(REG_INTENB)  & TMS34010_INT2))
  1083.         {
  1084.             LOG(("TMS34010#%d takes INT2\n", cpu_getactivecpu()));
  1085.             vector = 0xffffffa0;
  1086.             irqline = 1;
  1087.         }
  1088.  
  1089.         if (vector)
  1090.         {
  1091.             PUSH(PC);
  1092.             PUSH(GET_ST());
  1093.             RESET_ST();
  1094.             PC = RLONG(vector);
  1095.             change_pc29(PC);
  1096.  
  1097.             if (irqline >= 0)
  1098.                 (void)(*state.irq_callback)(irqline);
  1099.         }
  1100.     }
  1101. }
  1102.  
  1103.  
  1104. /* execute instructions on this CPU until icount expires */
  1105. int tms34010_execute(int cycles)
  1106. {
  1107.     /* Get out if CPU is halted. Absolutely no interrupts must be taken!!! */
  1108.     if (IOREG(REG_HSTCTLH) & 0x8000)
  1109.         return cycles;
  1110.  
  1111.     /* if the CPU's reset was deferred, do it now */
  1112.     if (state.reset_deferred)
  1113.     {
  1114.         state.reset_deferred = 0;
  1115.         PC = RLONG(0xffffffe0);
  1116. #if MAME_DEBUG
  1117. {
  1118.         extern int debug_key_pressed;
  1119.         debug_key_pressed = 1;
  1120. }
  1121. #endif
  1122.     }
  1123.  
  1124.     tms34010_ICount = cycles;
  1125.     change_pc29(PC)
  1126.     do
  1127.     {
  1128.         #ifdef    MAME_DEBUG
  1129.         if (mame_debug) { state.st = GET_ST(); MAME_Debug(); }
  1130.         #endif
  1131.         state.op = ROPCODE ();
  1132.         (*opcode_table[state.op >> 4])();
  1133.  
  1134.         #ifdef    MAME_DEBUG
  1135.         if (mame_debug) { state.st = GET_ST(); MAME_Debug(); }
  1136.         #endif
  1137.         state.op = ROPCODE ();
  1138.         (*opcode_table[state.op >> 4])();
  1139.  
  1140.         #ifdef    MAME_DEBUG
  1141.         if (mame_debug) { state.st = GET_ST(); MAME_Debug(); }
  1142.         #endif
  1143.         state.op = ROPCODE ();
  1144.         (*opcode_table[state.op >> 4])();
  1145.  
  1146.         #ifdef    MAME_DEBUG
  1147.         if (mame_debug) { state.st = GET_ST(); MAME_Debug(); }
  1148.         #endif
  1149.         state.op = ROPCODE ();
  1150.         (*opcode_table[state.op >> 4])();
  1151.  
  1152.     } while (tms34010_ICount > 0);
  1153.  
  1154.     return cycles - tms34010_ICount;
  1155. }
  1156.  
  1157. /****************************************************************************
  1158.  * Return a formatted string for a register
  1159.  ****************************************************************************/
  1160. const char *tms34010_info(void *context, int regnum)
  1161. {
  1162.     static char buffer[40][63+1];
  1163.     static int which = 0;
  1164.     TMS34010_Regs *r = context;
  1165.  
  1166.     which = ++which % 40;
  1167.     buffer[which][0] = '\0';
  1168.     if( !context )
  1169.         r = &state;
  1170.  
  1171.     switch( regnum )
  1172.     {
  1173.         case CPU_INFO_NAME: return "TMS34010";
  1174.         case CPU_INFO_FAMILY: return "Texas Instruments 34010";
  1175.         case CPU_INFO_VERSION: return "1.0";
  1176.         case CPU_INFO_FILE: return __FILE__;
  1177.         case CPU_INFO_CREDITS: return "Copyright (C) Alex Pasadyn/Zsolt Vasvari 1998\nParts based on code by Aaron Giles";
  1178.         case CPU_INFO_REG_LAYOUT: return (const char *)tms34010_reg_layout;
  1179.         case CPU_INFO_WIN_LAYOUT: return (const char *)tms34010_win_layout;
  1180.  
  1181.         case CPU_INFO_FLAGS:
  1182.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
  1183.                 r->st & 0x80000000 ? 'N':'.',
  1184.                 r->st & 0x40000000 ? 'C':'.',
  1185.                 r->st & 0x20000000 ? 'Z':'.',
  1186.                 r->st & 0x10000000 ? 'V':'.',
  1187.                 r->st & 0x08000000 ? '?':'.',
  1188.                 r->st & 0x04000000 ? '?':'.',
  1189.                 r->st & 0x02000000 ? 'P':'.',
  1190.                 r->st & 0x01000000 ? '?':'.',
  1191.                 r->st & 0x00800000 ? '?':'.',
  1192.                 r->st & 0x00400000 ? '?':'.',
  1193.                 r->st & 0x00200000 ? 'I':'.',
  1194.                 r->st & 0x00100000 ? '?':'.',
  1195.                 r->st & 0x00080000 ? '?':'.',
  1196.                 r->st & 0x00040000 ? '?':'.',
  1197.                 r->st & 0x00020000 ? '?':'.',
  1198.                 r->st & 0x00010000 ? '?':'.',
  1199.                 r->st & 0x00008000 ? '?':'.',
  1200.                 r->st & 0x00004000 ? '?':'.',
  1201.                 r->st & 0x00002000 ? '?':'.',
  1202.                 r->st & 0x00001000 ? '?':'.',
  1203.                 r->st & 0x00000800 ? 'E':'.',
  1204.                 r->st & 0x00000400 ? 'F':'.',
  1205.                 r->st & 0x00000200 ? 'F':'.',
  1206.                 r->st & 0x00000100 ? 'F':'.',
  1207.                 r->st & 0x00000080 ? 'F':'.',
  1208.                 r->st & 0x00000040 ? 'F':'.',
  1209.                 r->st & 0x00000020 ? 'E':'.',
  1210.                 r->st & 0x00000010 ? 'F':'.',
  1211.                 r->st & 0x00000008 ? 'F':'.',
  1212.                 r->st & 0x00000004 ? 'F':'.',
  1213.                 r->st & 0x00000002 ? 'F':'.',
  1214.                 r->st & 0x00000001 ? 'F':'.');
  1215.             break;
  1216.         case CPU_INFO_REG+TMS34010_PC: sprintf(buffer[which], "PC :%08X", r->pc); break;
  1217.         case CPU_INFO_REG+TMS34010_SP: sprintf(buffer[which], "SP :%08X", r->regs.a.a.Aregs[15]); break;
  1218.         case CPU_INFO_REG+TMS34010_ST: sprintf(buffer[which], "ST :%08X", r->st); break;
  1219.         case CPU_INFO_REG+TMS34010_A0: sprintf(buffer[which], "A0 :%08X", r->regs.a.a.Aregs[ 0]); break;
  1220.         case CPU_INFO_REG+TMS34010_A1: sprintf(buffer[which], "A1 :%08X", r->regs.a.a.Aregs[ 1]); break;
  1221.         case CPU_INFO_REG+TMS34010_A2: sprintf(buffer[which], "A2 :%08X", r->regs.a.a.Aregs[ 2]); break;
  1222.         case CPU_INFO_REG+TMS34010_A3: sprintf(buffer[which], "A3 :%08X", r->regs.a.a.Aregs[ 3]); break;
  1223.         case CPU_INFO_REG+TMS34010_A4: sprintf(buffer[which], "A4 :%08X", r->regs.a.a.Aregs[ 4]); break;
  1224.         case CPU_INFO_REG+TMS34010_A5: sprintf(buffer[which], "A5 :%08X", r->regs.a.a.Aregs[ 5]); break;
  1225.         case CPU_INFO_REG+TMS34010_A6: sprintf(buffer[which], "A6 :%08X", r->regs.a.a.Aregs[ 6]); break;
  1226.         case CPU_INFO_REG+TMS34010_A7: sprintf(buffer[which], "A7 :%08X", r->regs.a.a.Aregs[ 7]); break;
  1227.         case CPU_INFO_REG+TMS34010_A8: sprintf(buffer[which], "A8 :%08X", r->regs.a.a.Aregs[ 8]); break;
  1228.         case CPU_INFO_REG+TMS34010_A9: sprintf(buffer[which], "A9 :%08X", r->regs.a.a.Aregs[ 9]); break;
  1229.         case CPU_INFO_REG+TMS34010_A10: sprintf(buffer[which],"A10:%08X", r->regs.a.a.Aregs[10]); break;
  1230.         case CPU_INFO_REG+TMS34010_A11: sprintf(buffer[which],"A11:%08X", r->regs.a.a.Aregs[11]); break;
  1231.         case CPU_INFO_REG+TMS34010_A12: sprintf(buffer[which],"A12:%08X", r->regs.a.a.Aregs[12]); break;
  1232.         case CPU_INFO_REG+TMS34010_A13: sprintf(buffer[which],"A13:%08X", r->regs.a.a.Aregs[13]); break;
  1233.         case CPU_INFO_REG+TMS34010_A14: sprintf(buffer[which],"A14:%08X", r->regs.a.a.Aregs[14]); break;
  1234.         case CPU_INFO_REG+TMS34010_B0: sprintf(buffer[which], "B0 :%08X", r->regs.Bregs[ 0<<4]); break;
  1235.         case CPU_INFO_REG+TMS34010_B1: sprintf(buffer[which], "B1 :%08X", r->regs.Bregs[ 1<<4]); break;
  1236.         case CPU_INFO_REG+TMS34010_B2: sprintf(buffer[which], "B2 :%08X", r->regs.Bregs[ 2<<4]); break;
  1237.         case CPU_INFO_REG+TMS34010_B3: sprintf(buffer[which], "B3 :%08X", r->regs.Bregs[ 3<<4]); break;
  1238.         case CPU_INFO_REG+TMS34010_B4: sprintf(buffer[which], "B4 :%08X", r->regs.Bregs[ 4<<4]); break;
  1239.         case CPU_INFO_REG+TMS34010_B5: sprintf(buffer[which], "B5 :%08X", r->regs.Bregs[ 5<<4]); break;
  1240.         case CPU_INFO_REG+TMS34010_B6: sprintf(buffer[which], "B6 :%08X", r->regs.Bregs[ 6<<4]); break;
  1241.         case CPU_INFO_REG+TMS34010_B7: sprintf(buffer[which], "B7 :%08X", r->regs.Bregs[ 7<<4]); break;
  1242.         case CPU_INFO_REG+TMS34010_B8: sprintf(buffer[which], "B8 :%08X", r->regs.Bregs[ 8<<4]); break;
  1243.         case CPU_INFO_REG+TMS34010_B9: sprintf(buffer[which], "B9 :%08X", r->regs.Bregs[ 9<<4]); break;
  1244.         case CPU_INFO_REG+TMS34010_B10: sprintf(buffer[which],"B10:%08X", r->regs.Bregs[10<<4]); break;
  1245.         case CPU_INFO_REG+TMS34010_B11: sprintf(buffer[which],"B11:%08X", r->regs.Bregs[11<<4]); break;
  1246.         case CPU_INFO_REG+TMS34010_B12: sprintf(buffer[which],"B12:%08X", r->regs.Bregs[12<<4]); break;
  1247.         case CPU_INFO_REG+TMS34010_B13: sprintf(buffer[which],"B13:%08X", r->regs.Bregs[13<<4]); break;
  1248.         case CPU_INFO_REG+TMS34010_B14: sprintf(buffer[which],"B14:%08X", r->regs.Bregs[14<<4]); break;
  1249.     }
  1250.     return buffer[which];
  1251. }
  1252.  
  1253. unsigned tms34010_dasm(char *buffer, unsigned pc)
  1254. {
  1255. #ifdef MAME_DEBUG
  1256.     return Dasm34010(buffer,pc);
  1257. #else
  1258.     sprintf( buffer, "$%04X", cpu_readop16(pc>>3) );
  1259.     return 2;
  1260. #endif
  1261. }
  1262.  
  1263.  
  1264. /*###################################################################################################
  1265. **    PIXEL OPS
  1266. **#################################################################################################*/
  1267.  
  1268. static UINT32 (*pixel_write_ops[4][5])(UINT32, UINT32)    =
  1269. {
  1270.     {write_pixel_1,     write_pixel_2,     write_pixel_4,     write_pixel_8,     write_pixel_16},
  1271.     {write_pixel_r_1,   write_pixel_r_2,   write_pixel_r_4,   write_pixel_r_8,   write_pixel_r_16},
  1272.     {write_pixel_t_1,   write_pixel_t_2,   write_pixel_t_4,   write_pixel_t_8,   write_pixel_t_16},
  1273.     {write_pixel_r_t_1, write_pixel_r_t_2, write_pixel_r_t_4, write_pixel_r_t_8, write_pixel_r_t_16}
  1274. };
  1275.  
  1276. static UINT32 (*pixel_read_ops[5])(UINT32 address) =
  1277. {
  1278.     read_pixel_1, read_pixel_2, read_pixel_4, read_pixel_8, read_pixel_16
  1279. };
  1280.  
  1281.  
  1282. static void set_pixel_function(TMS34010_Regs *context)
  1283. {
  1284.     UINT32 i1,i2;
  1285.  
  1286.     if (CONTEXT_IOREG(context, REG_DPYCTL) & 0x0800)
  1287.     {
  1288.         /* Shift Register Transfer */
  1289.         context->pixel_write = write_pixel_shiftreg;
  1290.         context->pixel_read  = read_pixel_shiftreg;
  1291.         return;
  1292.     }
  1293.  
  1294.     switch (CONTEXT_IOREG(context, REG_PSIZE))
  1295.     {
  1296.     default:
  1297.     case 0x01: i2 = 0; break;
  1298.     case 0x02: i2 = 1; break;
  1299.     case 0x04: i2 = 2; break;
  1300.     case 0x08: i2 = 3; break;
  1301.     case 0x10: i2 = 4; break;
  1302.     }
  1303.  
  1304.     if (context->transparency)
  1305.     {
  1306.         if (context->raster_op)
  1307.         {
  1308.             i1 = 3;
  1309.         }
  1310.         else
  1311.         {
  1312.             i1 = 2;
  1313.         }
  1314.     }
  1315.     else
  1316.     {
  1317.         if (context->raster_op)
  1318.         {
  1319.             i1 = 1;
  1320.         }
  1321.         else
  1322.         {
  1323.             i1 = 0;
  1324.         }
  1325.     }
  1326.  
  1327.     context->pixel_write = pixel_write_ops[i1][i2];
  1328.     context->pixel_read  = pixel_read_ops [i2];
  1329. }
  1330.  
  1331.  
  1332. /*###################################################################################################
  1333. **    RASTER OPS
  1334. **#################################################################################################*/
  1335.  
  1336. static INT32 (*raster_ops[32]) (INT32 newpix, INT32 oldpix) =
  1337. {
  1338.                0, raster_op_1 , raster_op_2 , raster_op_3,
  1339.     raster_op_4 , raster_op_5 , raster_op_6 , raster_op_7,
  1340.     raster_op_8 , raster_op_9 , raster_op_10, raster_op_11,
  1341.     raster_op_12, raster_op_13, raster_op_14, raster_op_15,
  1342.     raster_op_16, raster_op_17, raster_op_18, raster_op_19,
  1343.     raster_op_20, raster_op_21,            0,            0,
  1344.                0,            0,            0,            0,
  1345.                0,            0,            0,            0,
  1346. };
  1347.  
  1348.  
  1349. static void set_raster_op(TMS34010_Regs *context)
  1350. {
  1351.     context->raster_op = raster_ops[(IOREG(REG_CONTROL) >> 10) & 0x1f];
  1352. }
  1353.  
  1354.  
  1355. /*###################################################################################################
  1356. **    VIDEO TIMING HELPERS
  1357. **#################################################################################################*/
  1358.  
  1359. INLINE int scanline_to_vcount(TMS34010_Regs *context, int scanline)
  1360. {
  1361.     if (Machine->drv->visible_area.min_y == 0)
  1362.         scanline += CONTEXT_IOREG(context, REG_VEBLNK);
  1363.     if (scanline > CONTEXT_IOREG(context, REG_VTOTAL))
  1364.         scanline -= CONTEXT_IOREG(context, REG_VTOTAL);
  1365.     return scanline;
  1366. }
  1367.  
  1368.  
  1369. INLINE int vcount_to_scanline(TMS34010_Regs *context, int vcount)
  1370. {
  1371.     if (Machine->drv->visible_area.min_y == 0)
  1372.         vcount -= CONTEXT_IOREG(context, REG_VEBLNK);
  1373.     if (vcount < 0)
  1374.         vcount += CONTEXT_IOREG(context, REG_VTOTAL);
  1375.     if (vcount > Machine->drv->visible_area.max_y)
  1376.         vcount = 0;
  1377.     return vcount;
  1378. }
  1379.  
  1380.  
  1381. static void update_display_address(TMS34010_Regs *context, int vcount)
  1382. {
  1383.     UINT32 dpyadr = CONTEXT_IOREG(context, REG_DPYADR) & 0xfffc;
  1384.     UINT32 dpytap = CONTEXT_IOREG(context, REG_DPYTAP) & 0x3fff;
  1385.     INT32 dudate = CONTEXT_IOREG(context, REG_DPYCTL) & 0x03fc;
  1386.     int org = CONTEXT_IOREG(context, REG_DPYCTL) & 0x0400;
  1387.     int scans = (CONTEXT_IOREG(context, REG_DPYSTRT) & 3) + 1;
  1388.  
  1389.     /* anytime during VBLANK is effectively the start of the next frame */
  1390.     if (vcount >= CONTEXT_IOREG(context, REG_VSBLNK) || vcount <= CONTEXT_IOREG(context, REG_VEBLNK))
  1391.         context->last_update_vcount = vcount = CONTEXT_IOREG(context, REG_VEBLNK);
  1392.  
  1393.     /* otherwise, compute the updated address */
  1394.     else
  1395.     {
  1396.         int rows = vcount - context->last_update_vcount;
  1397.         if (rows < 0) rows += CONTEXT_IOREG(context, REG_VCOUNT);
  1398.         dpyadr -= rows * dudate / scans;
  1399.         CONTEXT_IOREG(context, REG_DPYADR) = dpyadr | (CONTEXT_IOREG(context, REG_DPYADR) & 0x0003);
  1400.         context->last_update_vcount = vcount;
  1401.     }
  1402.  
  1403.     /* now compute the actual address */
  1404.     if (org == 0) dpyadr ^= 0xfffc;
  1405.     dpyadr <<= 8;
  1406.     dpyadr |= dpytap << 4;
  1407.  
  1408.     /* callback */
  1409.     if (context->config->display_addr_changed)
  1410.     {
  1411.         if (org != 0) dudate = -dudate;
  1412.         (*context->config->display_addr_changed)(dpyadr & 0x00ffffff, (dudate << 8) / scans, vcount_to_scanline(context, vcount));
  1413.     }
  1414. }
  1415.  
  1416.  
  1417. static void vsblnk_callback(int cpunum)
  1418. {
  1419.     /* reset timer for next frame */
  1420.     double interval = TIME_IN_HZ(Machine->drv->frames_per_second);
  1421.     TMS34010_Regs *context = FINDCONTEXT(cpunum);
  1422.     vsblnk_timer[cpunum] = timer_set(interval, cpunum, vsblnk_callback);
  1423.     CONTEXT_IOREG(context, REG_DPYADR) = CONTEXT_IOREG(context, REG_DPYSTRT);
  1424.     update_display_address(context, CONTEXT_IOREG(context, REG_VSBLNK));
  1425. }
  1426.  
  1427.  
  1428. static void dpyint_callback(int cpunum)
  1429. {
  1430.     /* reset timer for next frame */
  1431.     TMS34010_Regs *context = FINDCONTEXT(cpunum);
  1432.     double interval = TIME_IN_HZ(Machine->drv->frames_per_second);
  1433.     dpyint_timer[cpunum] = timer_set(interval, cpunum, dpyint_callback);
  1434.     cpu_generate_internal_interrupt(cpunum, TMS34010_DI);
  1435.  
  1436.     /* allow a callback so we can update before they are likely to do nasty things */
  1437.     if (context->config->display_int_callback)
  1438.         (*context->config->display_int_callback)(vcount_to_scanline(context, CONTEXT_IOREG(context, REG_DPYINT)));
  1439. }
  1440.  
  1441.  
  1442. static void update_timers(int cpunum, TMS34010_Regs *context)
  1443. {
  1444.     int dpyint = CONTEXT_IOREG(context, REG_DPYINT);
  1445.     int vsblnk = CONTEXT_IOREG(context, REG_VSBLNK);
  1446.  
  1447.     /* remove any old timers */
  1448.     if (dpyint_timer[cpunum])
  1449.         timer_remove(dpyint_timer[cpunum]);
  1450.     if (vsblnk_timer[cpunum])
  1451.         timer_remove(vsblnk_timer[cpunum]);
  1452.  
  1453.     /* set new timers */
  1454.     dpyint_timer[cpunum] = timer_set(cpu_getscanlinetime(vcount_to_scanline(context, dpyint)), cpunum, dpyint_callback);
  1455.     vsblnk_timer[cpunum] = timer_set(cpu_getscanlinetime(vcount_to_scanline(context, vsblnk)), cpunum, vsblnk_callback);
  1456. }
  1457.  
  1458.  
  1459. /*###################################################################################################
  1460. **    I/O REGISTER WRITES
  1461. **#################################################################################################*/
  1462.  
  1463. static const char *ioreg_name[] =
  1464. {
  1465.     "HESYNC", "HEBLNK", "HSBLNK", "HTOTAL",
  1466.     "VESYNC", "VEBLNK", "VSBLNK", "VTOTAL",
  1467.     "DPYCTL", "DPYSTART", "DPYINT", "CONTROL",
  1468.     "HSTDATA", "HSTADRL", "HSTADRH", "HSTCTLL",
  1469.     "HSTCTLH", "INTENB", "INTPEND", "CONVSP",
  1470.     "CONVDP", "PSIZE", "PMASK", "RESERVED",
  1471.     "RESERVED", "RESERVED", "RESERVED", "DPYTAP",
  1472.     "HCOUNT", "VCOUNT", "DPYADR", "REFCNT"
  1473. };
  1474.  
  1475. static void common_io_register_w(int cpunum, TMS34010_Regs *context, int reg, int data)
  1476. {
  1477.     int oldreg, newreg;
  1478.  
  1479.     /* Set register */
  1480.     reg >>= 1;
  1481.     oldreg = CONTEXT_IOREG(context, reg);
  1482.     CONTEXT_IOREG(context, reg) = data;
  1483.  
  1484.     switch (reg)
  1485.     {
  1486.         case REG_DPYINT:
  1487.             if (data != oldreg || !dpyint_timer[cpunum])
  1488.                 update_timers(cpunum, context);
  1489.             break;
  1490.  
  1491.         case REG_VSBLNK:
  1492.             if (data != oldreg || !vsblnk_timer[cpunum])
  1493.                 update_timers(cpunum, context);
  1494.             break;
  1495.  
  1496.         case REG_VEBLNK:
  1497.             if (data != oldreg)
  1498.                 update_timers(cpunum, context);
  1499.             break;
  1500.  
  1501.         case REG_CONTROL:
  1502.             context->transparency = data & 0x20;
  1503.             context->window_checking = (data >> 6) & 0x03;
  1504.             set_raster_op(context);
  1505.             set_pixel_function(context);
  1506.             break;
  1507.  
  1508.         case REG_PSIZE:
  1509.             set_pixel_function(context);
  1510.  
  1511.             switch (data)
  1512.             {
  1513.                 default:
  1514.                 case 0x01: context->xytolshiftcount2 = 0; break;
  1515.                 case 0x02: context->xytolshiftcount2 = 1; break;
  1516.                 case 0x04: context->xytolshiftcount2 = 2; break;
  1517.                 case 0x08: context->xytolshiftcount2 = 3; break;
  1518.                 case 0x10: context->xytolshiftcount2 = 4; break;
  1519.             }
  1520.             break;
  1521.  
  1522.         case REG_PMASK:
  1523.             if (data) logerror("Plane masking not supported. PC=%08X\n", cpu_get_pc());
  1524.             break;
  1525.  
  1526.         case REG_DPYCTL:
  1527.             set_pixel_function(context);
  1528.             if ((oldreg ^ data) & 0x03fc)
  1529.                 update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
  1530.             break;
  1531.  
  1532.         case REG_DPYADR:
  1533.             if (data != oldreg)
  1534.             {
  1535.                 context->last_update_vcount = scanline_to_vcount(context, cpu_getscanline());
  1536.                 update_display_address(context, context->last_update_vcount);
  1537.             }
  1538.             break;
  1539.  
  1540.         case REG_DPYSTRT:
  1541.             if (data != oldreg)
  1542.                 update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
  1543.             break;
  1544.  
  1545.         case REG_DPYTAP:
  1546.             if ((oldreg ^ data) & 0x3fff)
  1547.                 update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
  1548.             break;
  1549.  
  1550.         case REG_HSTCTLH:
  1551.             /* if the CPU is halting itself, stop execution right away */
  1552.             if ((data & 0x8000) && context == &state)
  1553.                 tms34010_ICount = 0;
  1554.             cpu_set_halt_line(cpunum, (data & 0x8000) ? ASSERT_LINE : CLEAR_LINE);
  1555.  
  1556.             /* NMI issued? */
  1557.             if (data & 0x0100)
  1558.                 cpu_generate_internal_interrupt(cpunum, TMS34010_NMI);
  1559.             break;
  1560.  
  1561.         case REG_HSTCTLL:
  1562.             /* the TMS34010 can change MSGOUT, can set INTOUT, and can clear INTIN */
  1563.             if (cpunum == cpu_getactivecpu())
  1564.             {
  1565.                 newreg = (oldreg & 0xff8f) | (data & 0x0070);
  1566.                 newreg |= data & 0x0080;
  1567.                 newreg &= data | ~0x0008;
  1568.             }
  1569.  
  1570.             /* the host can change MSGIN, can set INTIN, and can clear INTOUT */
  1571.             else
  1572.             {
  1573.                 newreg = (oldreg & 0xfff8) | (data & 0x0007);
  1574.                 newreg &= data | ~0x0080;
  1575.                 newreg |= data & 0x0008;
  1576.             }
  1577.             CONTEXT_IOREG(context, reg) = newreg;
  1578.  
  1579.             /* output interrupt? */
  1580.             if (!(oldreg & 0x0080) && (newreg & 0x0080))
  1581.             {
  1582.                 logerror("CPU#%d Output int = 1\n", cpunum);
  1583.                 if (context->config->output_int)
  1584.                     (*context->config->output_int)(1);
  1585.             }
  1586.             else if ((oldreg & 0x0080) && !(newreg & 0x0080))
  1587.             {
  1588.                 logerror("CPU#%d Output int = 0\n", cpunum);
  1589.                 if (context->config->output_int)
  1590.                     (*context->config->output_int)(0);
  1591.             }
  1592.  
  1593.             /* input interrupt? (should really be state-based, but the functions don't exist!) */
  1594.             if (!(oldreg & 0x0008) && (newreg & 0x0008))
  1595.             {
  1596.                 logerror("CPU#%d Input int = 1\n", cpunum);
  1597.                 cpu_generate_internal_interrupt(cpunum, TMS34010_HI);
  1598.             }
  1599.             else if ((oldreg & 0x0008) && !(newreg & 0x0008))
  1600.             {
  1601.                 logerror("CPU#%d Input int = 0\n", cpunum);
  1602.                 CONTEXT_IOREG(context, REG_INTPEND) &= ~TMS34010_HI;
  1603.             }
  1604.             break;
  1605.  
  1606.         case REG_CONVDP:
  1607.             context->xytolshiftcount1 = (~data & 0x0f);
  1608.             break;
  1609.  
  1610.         case REG_INTENB:
  1611.             if (CONTEXT_IOREG(context, REG_INTENB) & CONTEXT_IOREG(context, REG_INTPEND))
  1612.                 check_interrupt();
  1613.             break;
  1614.     }
  1615.  
  1616.     logerror("CPU#%d: %s = %04X (%d)\n", cpunum, ioreg_name[reg], CONTEXT_IOREG(context, reg), cpu_getscanline());
  1617. }
  1618.  
  1619. WRITE_HANDLER( TMS34010_io_register_w )
  1620. {
  1621.     if (!host_interface_context)
  1622.         common_io_register_w(cpu_getactivecpu(), &state, offset, data);
  1623.     else
  1624.         common_io_register_w(host_interface_cpu, host_interface_context, offset, data);
  1625. }
  1626.  
  1627.  
  1628. /*###################################################################################################
  1629. **    I/O REGISTER READS
  1630. **#################################################################################################*/
  1631.  
  1632. static int common_io_register_r(int cpunum, TMS34010_Regs *context, int reg)
  1633. {
  1634.     int result, total;
  1635.  
  1636.     reg >>= 1;
  1637.     logerror("CPU#%d: read %s\n", cpunum, ioreg_name[reg]);
  1638.  
  1639.     switch (reg)
  1640.     {
  1641.         case REG_VCOUNT:
  1642.             return scanline_to_vcount(context, cpu_getscanline());
  1643.  
  1644.         case REG_HCOUNT:
  1645.  
  1646.             /* scale the horizontal position from screen width to HTOTAL */
  1647.             result = cpu_gethorzbeampos();
  1648.             total = CONTEXT_IOREG(context, REG_HTOTAL);
  1649.             result = result * total / Machine->drv->screen_width;
  1650.  
  1651.             /* offset by the HBLANK end */
  1652.             result += CONTEXT_IOREG(context, REG_HEBLNK);
  1653.  
  1654.             /* wrap around */
  1655.             if (result > total)
  1656.                 result -= total;
  1657.             return result;
  1658.  
  1659.         case REG_DPYADR:
  1660.             update_display_address(context, scanline_to_vcount(context, cpu_getscanline()));
  1661.             break;
  1662.     }
  1663.  
  1664.     return CONTEXT_IOREG(context, reg);
  1665. }
  1666.  
  1667.  
  1668. READ_HANDLER( TMS34010_io_register_r )
  1669. {
  1670.     if (!host_interface_context)
  1671.         return common_io_register_r(cpu_getactivecpu(), &state, offset);
  1672.     else
  1673.         return common_io_register_r(host_interface_cpu, host_interface_context, offset);
  1674. }
  1675.  
  1676.  
  1677. /*###################################################################################################
  1678. **    UTILITY FUNCTIONS
  1679. **#################################################################################################*/
  1680.  
  1681. void TMS34010_set_stack_base(int cpu, UINT8* stackbase_p, UINT32 stackoffs_p)
  1682. {
  1683.     stackbase[cpu] = stackbase_p;
  1684.     stackoffs[cpu] = stackoffs_p;
  1685. }
  1686.  
  1687.  
  1688. int TMS34010_io_display_blanked(int cpu)
  1689. {
  1690.     TMS34010_Regs* context = FINDCONTEXT(cpu);
  1691.     return (!(context->IOregs[REG_DPYCTL] & 0x8000));
  1692. }
  1693.  
  1694.  
  1695. int TMS34010_get_DPYSTRT(int cpu)
  1696. {
  1697.     TMS34010_Regs* context = FINDCONTEXT(cpu);
  1698.     return context->IOregs[REG_DPYSTRT];
  1699. }
  1700.  
  1701.  
  1702. /*###################################################################################################
  1703. **    SAVE STATE
  1704. **#################################################################################################*/
  1705.  
  1706. void TMS34010_State_Save(int cpunum, void *f)
  1707. {
  1708.     TMS34010_Regs* context = FINDCONTEXT(cpunum);
  1709.     osd_fwrite(f,context,sizeof(state));
  1710.     osd_fwrite(f,&tms34010_ICount,sizeof(tms34010_ICount));
  1711.     osd_fwrite(f,state.shiftreg,sizeof(SHIFTREG_SIZE));
  1712. }
  1713.  
  1714.  
  1715. void TMS34010_State_Load(int cpunum, void *f)
  1716. {
  1717.     /* Don't reload the following */
  1718.     unsigned short* shiftreg_save = state.shiftreg;
  1719.  
  1720.     TMS34010_Regs* context = FINDCONTEXT(cpunum);
  1721.  
  1722.     osd_fread(f,context,sizeof(state));
  1723.     osd_fread(f,&tms34010_ICount,sizeof(tms34010_ICount));
  1724.     change_pc29(PC);
  1725.     SET_FW();
  1726.     TMS34010_io_register_w(REG_DPYINT<<1,IOREG(REG_DPYINT));
  1727.     set_raster_op(&state);
  1728.     set_pixel_function(&state);
  1729.  
  1730.     state.shiftreg      = shiftreg_save;
  1731.  
  1732.     osd_fread(f,state.shiftreg,sizeof(SHIFTREG_SIZE));
  1733. }
  1734.  
  1735.  
  1736. /*###################################################################################################
  1737. **    HOST INTERFACE WRITES
  1738. **#################################################################################################*/
  1739.  
  1740. void tms34010_host_w(int cpunum, int reg, int data)
  1741. {
  1742.     TMS34010_Regs* context = FINDCONTEXT(cpunum);
  1743.     const struct cpu_interface *interface;
  1744.     unsigned int addr;
  1745.     int oldcpu;
  1746.  
  1747.     switch (reg)
  1748.     {
  1749.         /* upper 16 bits of the address */
  1750.         case TMS34010_HOST_ADDRESS_H:
  1751.             CONTEXT_IOREG(context, REG_HSTADRH) = data;
  1752.             break;
  1753.  
  1754.         /* lower 16 bits of the address */
  1755.         case TMS34010_HOST_ADDRESS_L:
  1756.             CONTEXT_IOREG(context, REG_HSTADRL) = data & 0xfff0;
  1757.             break;
  1758.  
  1759.         /* actual data */
  1760.         case TMS34010_HOST_DATA:
  1761.  
  1762.             /* swap to the target cpu */
  1763.             oldcpu = cpu_getactivecpu();
  1764.             memorycontextswap(cpunum);
  1765.  
  1766.             /* write to the address */
  1767.             host_interface_cpu = cpunum;
  1768.             host_interface_context = context;
  1769.             addr = (CONTEXT_IOREG(context, REG_HSTADRH) << 16) | CONTEXT_IOREG(context, REG_HSTADRL);
  1770.             TMS34010_WRMEM_WORD(TOBYTE(addr), data);
  1771.             host_interface_context = NULL;
  1772.  
  1773.             /* optional postincrement */
  1774.             if (CONTEXT_IOREG(context, REG_HSTCTLH) & 0x0800)
  1775.             {
  1776.                 addr += 0x10;
  1777.                 CONTEXT_IOREG(context, REG_HSTADRH) = addr >> 16;
  1778.                 CONTEXT_IOREG(context, REG_HSTADRL) = (UINT16)addr;
  1779.             }
  1780.  
  1781.             /* swap back */
  1782.             memorycontextswap(oldcpu);
  1783.             interface = &cpuintf[Machine->drv->cpu[oldcpu].cpu_type & ~CPU_FLAGS_MASK];
  1784.             (*interface->set_op_base)((*interface->get_pc)());
  1785.             break;
  1786.  
  1787.         /* control register */
  1788.         case TMS34010_HOST_CONTROL:
  1789.             common_io_register_w(cpunum, context, REG_HSTCTLH * 2, data & 0xff00);
  1790.             common_io_register_w(cpunum, context, REG_HSTCTLL * 2, data & 0x00ff);
  1791.             break;
  1792.  
  1793.         /* error case */
  1794.         default:
  1795.             logerror("tms34010_host_control_w called on invalid register %d\n", reg);
  1796.             break;
  1797.     }
  1798. }
  1799.  
  1800.  
  1801. /*###################################################################################################
  1802. **    HOST INTERFACE READS
  1803. **#################################################################################################*/
  1804.  
  1805. int tms34010_host_r(int cpunum, int reg)
  1806. {
  1807.     TMS34010_Regs* context = FINDCONTEXT(cpunum);
  1808.     const struct cpu_interface *interface;
  1809.     unsigned int addr;
  1810.     int oldcpu, result;
  1811.  
  1812.     switch (reg)
  1813.     {
  1814.         /* upper 16 bits of the address */
  1815.         case TMS34010_HOST_ADDRESS_H:
  1816.             return CONTEXT_IOREG(context, REG_HSTADRH);
  1817.  
  1818.         /* lower 16 bits of the address */
  1819.         case TMS34010_HOST_ADDRESS_L:
  1820.             return CONTEXT_IOREG(context, REG_HSTADRL);
  1821.  
  1822.         /* actual data */
  1823.         case TMS34010_HOST_DATA:
  1824.  
  1825.             /* swap to the target cpu */
  1826.             oldcpu = cpu_getactivecpu();
  1827.             memorycontextswap(cpunum);
  1828.  
  1829.             /* read from the address */
  1830.             host_interface_cpu = cpunum;
  1831.             host_interface_context = context;
  1832.             addr = (CONTEXT_IOREG(context, REG_HSTADRH) << 16) | CONTEXT_IOREG(context, REG_HSTADRL);
  1833.             result = TMS34010_RDMEM_WORD(TOBYTE(addr));
  1834.             host_interface_context = NULL;
  1835.  
  1836.             /* optional postincrement (it says preincrement, but data is preloaded, so it
  1837.                is effectively a postincrement */
  1838.             if (CONTEXT_IOREG(context, REG_HSTCTLH) & 0x1000)
  1839.             {
  1840.                 addr += 0x10;
  1841.                 CONTEXT_IOREG(context, REG_HSTADRH) = addr >> 16;
  1842.                 CONTEXT_IOREG(context, REG_HSTADRL) = (UINT16)addr;
  1843.             }
  1844.  
  1845.             /* swap back */
  1846.             memorycontextswap(oldcpu);
  1847.             interface = &cpuintf[Machine->drv->cpu[oldcpu].cpu_type & ~CPU_FLAGS_MASK];
  1848.             (*interface->set_op_base)((*interface->get_pc)());
  1849.             return result;
  1850.  
  1851.         /* control register */
  1852.         case TMS34010_HOST_CONTROL:
  1853.             return (CONTEXT_IOREG(context, REG_HSTCTLH) & 0xff00) | (CONTEXT_IOREG(context, REG_HSTCTLL) & 0x00ff);
  1854.     }
  1855.  
  1856.     /* error case */
  1857.     logerror("tms34010_host_control_r called on invalid register %d\n", reg);
  1858.     return 0;
  1859. }
  1860.